package com.dy.yandi.biz.controller;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dy.yandi.api.client.demo.model.entity.DataChartDO;
import com.dy.yandi.api.client.demo.model.vo.DataChartVO;
import com.dy.yandi.api.client.requirement.model.DesignBonus;
import com.dy.yandi.api.client.requirement.model.dto.DesignBonusDto;
import com.dy.yandi.api.client.requirement.model.dto.PerformanceDto;
import com.dy.yandi.api.client.requirement.model.dto.PerformanceVo;
import com.dy.yandi.api.client.requirement.model.dto.VirtualData;
import com.dy.yandi.api.client.requirement.service.DesignBonusService;
import com.dy.yandi.api.enums.DesignEnum;
import com.dy.yandi.biz.service.DataChartService;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.admin.api.dto.SysUserInfo;
import com.pig4cloud.pig.admin.api.dto.UserInfo;
import com.pig4cloud.pig.admin.api.entity.SysDictItem;
import com.pig4cloud.pig.admin.api.entity.SysUserTenant;
import com.pig4cloud.pig.admin.api.feign.RemoteDeptGroupService;
import com.pig4cloud.pig.admin.api.feign.RemoteDictService;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.BigDecimalUtils;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.pig.common.security.service.PigUser;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 绩效奖金表
 * @author  chengang
 * @version  2021-09-28 13:43:52
 * table: design_bonus
 */
@Slf4j
@RestController
@RequestMapping("/designBonus")
@RequiredArgsConstructor
public class DesignBonusController {
	
    private final DesignBonusService designBonusService;
	private final RemoteUserService remoteUserService;
	private final RemoteDictService remoteDictService;

	private final String DESIGN_MANAGER_DICT_TYPE = "design_manager";


	/**
	 * 绩效列表
	 * @param searchDto
	 * @return
	 */
	@PostMapping("performance")
	public R performance(@RequestBody @Valid PerformanceDto searchDto) {
		/**
		 * 一期先实现功能
		 * 1.同一周期同一人做不同类型的需求，按最后所属组别计算
		 * 2.将用户从组别中删除(编辑用户取消组别),则绩效显示空
		 * 3.需求不是很明确的情况下，暂时将组别和需求类型做字典映射配置 label = 类型  value = 组别ID
		 */
		PigUser user = SecurityUtils.getUser();
		//Search用户集合
		List<Integer> searchUserList = Lists.newArrayList();
		//默认查询当前人
		searchUserList.add(user.getId());
		IPage<PerformanceVo> page = new Page<>();

		//根据组别获取需求类型
		if (searchDto.getDeptGroupId() == null) {return R.ok(page);}
		//获取当前组别下所有的用户
		List<SysUserTenant> userIdList = this.getUserListByGroupId(searchDto.getDeptGroupId());
		if (CollectionUtils.isNotEmpty(userIdList)) {
			searchUserList.clear();
			if (this.isManager()) {
				searchUserList.addAll(userIdList.stream().distinct().map(SysUserTenant::getUserId).collect(Collectors.toList()));
			} else {
				//防止用户人为删除选中的值-非主管只查询自己
				searchUserList.addAll(userIdList.stream().distinct().map(SysUserTenant::getUserId)
						.filter(v -> v.equals(user.getId())).collect(Collectors.toList()));
			}
			//用于计算团队分
			searchDto.setAllUserList(userIdList.stream().distinct().map(SysUserTenant::getUserId).collect(Collectors.toList()));
		}
		if (searchDto.getUserId() != null) {
			searchUserList.clear();
			searchUserList.add(searchDto.getUserId());
		}
		searchDto.setSearchUserList(searchUserList);
		return R.ok(designBonusService.getPerformance(searchDto));
	}

	private List<SysUserTenant> getUserListByGroupId(Integer groupId){
		R<List<SysUserTenant>> userIdList = remoteUserService.getUserListByGroupId(SecurityConstants.FROM_IN,groupId);
		if (userIdList.getCode() == 0) {
			return userIdList.getData();
		}
		return Lists.newArrayList();
	}


	/**
	 * 设置综合分
	 * 不重新计算，前端根据设置的综合分计算总分
	 * @param dto
	 * @return
	 */
	@PreAuthorize("@pms.hasPermission('DESIGN_SET_COMPREHENSIVECORE')")
    @SysLog("设置综合分")
	@PostMapping("/core")
	public R design4Core(@RequestBody @Valid DesignBonusDto dto) {
		R check = this.baseCheck(dto);
		if (check.getCode() == CommonConstants.FAIL) {
			return check;
		}
		PigUser user = SecurityUtils.getUser();
		//查询当前周期、用户是否已存在
		DesignBonus bonus = this.getDesignBonus(dto);
		if (bonus != null) {
			bonus.setComprehensiveScore(dto.getComprehensiveScore());
			bonus.setUpdateId(user.getId().longValue());
			designBonusService.updateById(bonus);
		} else {
			DesignBonus insertDto = new DesignBonus();
			//BeanUtils.copyProperties(dto,insertDto);
			insertDto.setPeriodType(dto.getPeriod());
			insertDto.setPeriodValue(dto.getPeriodValue());
			insertDto.setProducerId(dto.getUserId());
			insertDto.setComprehensiveScore(dto.getComprehensiveScore());
			insertDto.setCreateId(user.getId().longValue());
			insertDto.setUpdateId(user.getId().longValue());
			//设置综合分，默认总金额为 -1 奖金 -1 表示主管未计算
			insertDto.setBonus(new BigDecimal(-1));
			designBonusService.save(insertDto);
		}

		return R.ok();
	}

	/**
	 * 计算奖金
	 * @param dto
	 * @return
	 */
	@PreAuthorize("@pms.hasPermission('DESIGN_SET_BONUS')")
	@SysLog("计算奖金")
	@PostMapping("/bonus")
	public R design4Bonus(@RequestBody @Valid DesignBonusDto dto) {
		R check = this.baseCheck(dto);
		if (check.getCode() == CommonConstants.FAIL) {
			return check;
		}

		R check4Bonus = this.baseCheck4Bonus(dto);
		if (check4Bonus.getCode() == CommonConstants.FAIL) {
			return check4Bonus;
		}

		PigUser user = SecurityUtils.getUser();

		//可以偷懒直接pageSize传很大的值，直接调用分页接口即可...

		// 获取当前组所有人的绩效总分
		//因为存在团队有人离开，故不能取需求类型下所有人的绩效
		List<SysUserTenant> userIdList = this.getUserListByGroupId(dto.getSearchDeptGroupId());
		//用于计算团队分
		PerformanceDto searchDto = new PerformanceDto();
		searchDto.setStartDate(dto.getSearchStartDate());
		searchDto.setEndDate(dto.getSearchEndDate());
		searchDto.setDeptGroupId(dto.getSearchDeptGroupId());
		searchDto.setType(dto.getType());
		searchDto.setPeriod(dto.getPeriod());
		searchDto.setAllUserList(userIdList.stream().distinct().map(SysUserTenant::getUserId).collect(Collectors.toList()));
		List<PerformanceVo> listNoPage = designBonusService.getPerformanceNoPage(searchDto);
		//计算当前团队所有人的绩效-含有所有周期
		List<DataChartDO> allCostList = designBonusService.getAllMaterialCost(searchDto,listNoPage);
		//获取计算结果
		List<PerformanceVo> allScoreList = designBonusService.getCalcResult(listNoPage,allCostList,true,null);
		double bonusValue = 0.00;
		if (CollectionUtils.isNotEmpty(allScoreList)) {
			//按周期分组获取团队绩效
			Map<String,List<PerformanceVo>> periodMap = allScoreList.stream().collect(Collectors.groupingBy(PerformanceVo::getPeriodValue));
			allScoreList.forEach(item -> {
				//1.无需设置用户名、组别名
				//设置评价分数占比
				item.setEvaluate(designBonusService.calcEvaluate(item.getType(),new BigDecimal(item.getTotalScore())));
			});
			//计算奖金值
			//获取当前计算周期所有人的绩效
			List<PerformanceVo> currentPeriodList = periodMap.get(dto.getPeriodValue());
			//可以一次计算团队所有人的，目前设计的是前端页面逐个点击计算奖金
			bonusValue = this.calcBonus(dto.getTotalBonus(),dto.getUserId(),currentPeriodList);
		}

		//查询当前周期、用户是否已存在
		DesignBonus bonus = this.getDesignBonus(dto);
		if (bonus != null) {
			bonus.setTotalBonus(dto.getTotalBonus());
			bonus.setUpdateId(user.getId().longValue());
			bonus.setBonus(new BigDecimal(bonusValue));
			bonus.setCalcTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
			designBonusService.updateById(bonus);
		} else {
			DesignBonus insertDto = new DesignBonus();
//			BeanUtils.copyProperties(dto,insertDto);
			insertDto.setPeriodType(dto.getPeriod());
			insertDto.setPeriodValue(dto.getPeriodValue());
			insertDto.setProducerId(dto.getUserId());
			insertDto.setTotalBonus(dto.getTotalBonus());
			insertDto.setCreateId(user.getId().longValue());
			insertDto.setUpdateId(user.getId().longValue());
			insertDto.setBonus(new BigDecimal(bonusValue));
			insertDto.setCalcTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
			designBonusService.save(insertDto);
		}
		Map<String,String> result = new HashMap<>();
		DecimalFormat df = new DecimalFormat("#0.00");
		result.put("bonus",df.format(bonusValue));
		return R.ok(result);
	}

	private double calcBonus(BigDecimal totalBonus,Long userId,List<PerformanceVo> list){
		//当前计算对象的评价百分比
		List<PerformanceVo> userList = list.stream().filter(v -> v.getUserId().equals(userId.intValue())).collect(Collectors.toList());
		Integer userPercentage = userList.get(0).getEvaluate();
		Integer totalPercentage = list.stream().mapToInt(PerformanceVo::getEvaluate).sum();
		float dup = (float)userPercentage / 100;
		float dtp = (float)totalPercentage / 100;
		if (dtp == 0) {return 0;}
		double div = dup / dtp;
		return BigDecimalUtils.ceil(BigDecimalUtils.mul(totalBonus.doubleValue(),div),2);
	}

	private DesignBonus getDesignBonus(DesignBonusDto dto){
		return designBonusService.getOne(Wrappers.<DesignBonus>lambdaQuery()
				.eq(DesignBonus::getProducerId,dto.getUserId())
				.eq(DesignBonus::getPeriodType,dto.getPeriod())
				.eq(DesignBonus::getPeriodValue,dto.getPeriodValue())
				.eq(DesignBonus::getIsDeleted,0));
	}

	private R baseCheck(DesignBonusDto dto){
		if(dto.getUserId() == null) {
			return R.failed("制作人不能为空");
		}

		if (dto.getPeriod() == null) {
			return R.failed("周期类型不能为空");
		}

		if (StringUtils.isBlank(dto.getPeriodValue())) {
			return R.failed("周期值不能为空");
		}

		return R.ok();

	}

	private R baseCheck4Bonus(DesignBonusDto dto){

		if (dto.getTotalBonus() == null) {
			return R.failed("总金额不能为空");
		}

		//实时计算总分进而计算奖金
		if (StringUtils.isBlank(dto.getSearchStartDate())) {
			return R.failed("开始时间不能为空");
		}

		if (StringUtils.isBlank(dto.getSearchEndDate())) {
			return R.failed("结束时间不能为空");
		}

		if (dto.getSearchDeptGroupId() == null) {
			return R.failed("组别ID不能为空");
		}

		if (dto.getType() == null) {
			return R.failed("需求类型不能为空");
		}

//		if (!isMoney(dto.getTotalBonus().toString(),2)) {
//			return R.failed("奖金总额格式不正确");
//		}

		if (dto.getTotalBonus().compareTo(BigDecimal.ZERO) <=0) {
			return R.failed("奖金总额必须大于0元");
		}

		if (dto.getTotalBonus().compareTo(new BigDecimal(9999999.99)) >0) {
			return R.failed("奖金总额不能大于999999999元");
		}


		return R.ok();

	}

	private static boolean isMoney(String str, int digit) {
		Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0," + digit + "})?$");
		Matcher match = pattern.matcher(str);
		return match.matches();
	}

	private Boolean isManager(){
		Boolean result = false;
		//字典表获取设计师主管角色ID
		Integer managerId = -1;
		List<SysDictItem> dictItemList = this.getDict(DESIGN_MANAGER_DICT_TYPE);
		if (CollectionUtils.isNotEmpty(dictItemList)) {
			managerId = Integer.parseInt(dictItemList.get(0).getValue());
		}
		List<Integer> list = SecurityUtils.getRoles();
		if (list.contains(managerId)) {
			result = Boolean.TRUE;
		}
		return result;
	}

	private List<SysDictItem> getDict(String type){
		R<List<SysDictItem>> dict = remoteDictService.getDictByType4Inner(SecurityConstants.FROM_IN,type);
		if (dict.getCode()==0 && CollectionUtils.isNotEmpty(dict.getData())) {
			return dict.getData();
		}
		return Lists.newArrayList();
	}

}


